#include "wds_game.h"
#include "wds_sfx_manager.h"
#include "wds_sounds.h"
#include "wds_ui_animator.h"
#include "wds_ui_popupanimator.h"
#include "wds_game_editor.h"
#include "wds_ui_popupanimator.h"
#include "gen_game_state.h"
#include "wds_enemy_manager.h"
#include "wds_fade_blood.h"
#include "wds_bullet_manager.h"
#include "wds_pickup_manager.h"

#include "ui/ui_flexeffect.h"
#include "admanager/admanager.h"
#include "application/game_rms.h"
#include "application/game_application.h"
#include "font/font_manager.h"
#include "graphics/graphics_util.h"
#include "math/intersection.h"
#include "gameflow/ui_popup.h"
#include "num/rand.h"


bool	RenderOverUICallBack()
{
	//GENGameState::GetGame()->GetGameMatch5()->RenderOverUI();
	return true;
}

WDSGame::WDSGame(GENGameState* pGameState, const math::Vec2& MinBoundary, const math::Vec2& MaxBoundary) : m_pEditor(NULL),					 
					 m_pUIPause(NULL),					
					 m_pUISetting(NULL),
					 m_Scale(1.0f),
					 m_pGameState(pGameState),
					 m_NextEnemySpawn(0),
					 m_CurrentEnemySpawnRate(1.0f),
					 m_TimeDifficulty(1.0f)
{
	
	m_Player.SetGame(this, MinBoundary, MaxBoundary);	
	WDSEnemyManager::Instance().SetPlayer(&m_Player);

	if(m_pGameState)
	{
		for(int i = 0; i < 10; i++)
		{
			WDSEnemyManager::Instance().Spawn(WDSEnemy::ENEMY_TYPES_NORMAL, WDSEnemy::ENEMY_SPAWN_TYPE_EATING, m_pGameState->GetBG().GetOffset());
		}
	}

}

WDSGame::~WDSGame()
{
	UTIL_SAFE_DELETE(m_pEditor);
}


void		WDSGame::Render(const math::Vec2& Offset)
{	
	
	WDSFadeBloodManager::Instance().Render(Offset,m_Scale);
	m_Player.RenderShadow(Offset, m_Scale);	
	WDSEnemyManager::Instance().RenderShadow(Offset, m_Scale);	
	WDSEnemyManager::Instance().RenderDecal(Offset, m_Scale);	
	WDSEnemyManager::Instance().RenderDead(Offset, m_Scale);	

	m_Player.Render(Offset, m_Scale);
	WDSEnemyManager::Instance().Render(Offset, m_Scale);	
	WDSBulletManager::Instance().Render(Offset,m_Scale);
	WDSSFXManager::Instance().Render(Offset,m_Scale);
	WDSPickupManager::Instance().Render(Offset, m_Scale);
}




void		WDSGame::PostRender()
{
    WDSSFXManager::Instance().PostRender(math::Vec2(0,0),m_Scale);
	m_Player.RenderUI( m_Scale);
	
}

void		WDSGame::RenderDebug(const math::Vec2& Offset)
{
	FontManager::Instance().Print(math::Vec2(0.5f,0.5f),
								"%f,%f", 
								input::Mouse::Instance().GetPos().x,
								input::Mouse::Instance().GetPos().y
								); 

	WDSBulletManager::Instance().RenderDebug(Offset,m_Scale);
}



void		WDSGame::Tick(float dt,const math::Vec2& Offset)
{
	
	const float Backup_dt = dt;
	dt *= m_GameSpeed.Tick(Backup_dt);

	float X = 0.0f ,Y = 0.0f;	

	if( input::Keyboard::Instance().IsKeyDown(KEY_A) || input::Keyboard::Instance().IsKeyDown(KEY_LEFT))
		X = -1.0f;		
			
	if( input::Keyboard::Instance().IsKeyDown(KEY_W) || input::Keyboard::Instance().IsKeyDown(KEY_UP) )   		
		Y = -1.0f;			

	if( input::Keyboard::Instance().IsKeyDown(KEY_X)  || input::Keyboard::Instance().IsKeyDown(KEY_DOWN) )
		Y = 1.0f;

	if( input::Keyboard::Instance().IsKeyDown(KEY_D) || input::Keyboard::Instance().IsKeyDown(KEY_RIGHT))
		X = 1.0f;

	m_NextEnemySpawn -= dt;
	if(m_NextEnemySpawn <= 0 && m_pGameState)
	{
		m_NextEnemySpawn = m_CurrentEnemySpawnRate;

		//if(num::RAND32::Instance().RandInt(0,1) == 0)
			//WDSEnemyManager::Instance().Spawn(WDSEnemy::ENEMY_TYPES_NORMAL, WDSEnemy::ENEMY_SPAWN_TYPE_OFFSCREEN, m_pGameState->GetBG().GetOffset());
		//else
			//WDSEnemyManager::Instance().Spawn(WDSEnemy::ENEMY_TYPES_NORMAL, WDSEnemy::ENEMY_SPAWN_TYPE_GROUND, m_pGameState->GetBG().GetOffset());
	}
	
	m_Player.OnMOGAMotionEvent(X,Y);
	m_Player.Tick(dt, Backup_dt, Offset, m_Scale);

	WDSEnemyManager::Instance().Tick(	dt,
										m_TimeDifficulty,
										m_Player.GetSkill()->m_Reflex,  
										Offset);

	WDSFadeBloodManager::Instance().Tick(dt);
	WDSBulletManager::Instance().Tick(dt, Offset);
	WDSSFXManager::Instance().Tick(dt);
	WDSPickupManager::Instance().Tick(dt);
	WDSSounds::Instance().Tick(dt);
}


void		WDSGame::KeyPressed(input::Keyboard::KEY* pKey)
{
	float X = 0;
	float Y = 0;
		
}

void		WDSGame::MouseButtonDown(input::Mouse::BUTTON_STATE* pKey, const math::Vec2& Pos)
{
	m_Player.OnMouseDown(Pos);
}

void		WDSGame::MouseButtonReleased(input::Mouse::BUTTON_STATE* pKey, const math::Vec2& Pos)
{
	m_Player.OnMouseUp(Pos);	
}

void		WDSGame::MouseButtonPressed(input::Mouse::BUTTON_STATE* pKey, const math::Vec2& Pos)
{
	
}

void		WDSGame::MouseMove(const math::Vec2& From, const math::Vec2& To)
{
	m_Player.OnMouseMove(From,To);
}

void		WDSGame::MouseWheelMove(int WheelInfo, const math::Vec2& Pos)
{
	
}




bool		WDSGame::Clear()
{
	return true;
}

bool		WDSGame::Load(const std::string& File)
{

	return false;
}

bool	WDSGame::Save(const std::string& File)
{
	return false;
}


void	WDSGame::UpdateOffset(const math::Vec2& PlayerPos)
{
	const math::Vec2 MARGIN = math::Vec2(0.1f, 0.1f * GraphicsUtil::W2H);
	math::Vec2 Offset = m_pGameState->GetBG().GetOffset();
	math::Vec2 Pos = PlayerPos - Offset;
	float Delta = 0;
	bool UseMargin = true;

	if(UseMargin)
	{
		if(Pos.x < MARGIN.x)
		{	
			Delta = MARGIN.x - Pos.x;
			Offset.x -= Delta;
		}
		else if(Pos.x > 1.0f - MARGIN.x)
		{
			Delta = Pos.x - (1.0f - MARGIN.x);
			Offset.x += Delta;
		}

		if(Pos.y < MARGIN.y)
		{	
			Delta = MARGIN.y - Pos.y;
			Offset.y -= Delta;
		}
		else if(Pos.y > 1.0f - MARGIN.y)
		{
			Delta = Pos.y - (1.0f - MARGIN.y);
			Offset.y += Delta;
		}
	}
		

	if(m_pGameState)
	{
		m_pGameState->GetBG().SetOffset(Offset);
		//const math::Vec2 ActalBGOffset = m_pGameState->GetBG().GetOffset();
		//m_Offset = ActalBGOffset - math::Vec2(0.5f,0.5f);
		
	}
	
}

void	WDSGame::GameSpeed::Activate()
{
	const float FLAHS_STEP_DURATION = 15.0f;
	
	m_CurrentTickScale = 0;;
	m_IsGoingDown = true;
	m_Counter = FLAHS_STEP_DURATION;
	if(!m_IsActivate)
		m_CurrentTickScale = 1.0f;

	m_IsActivate = true;;

}

float	WDSGame::GameSpeed::Tick(float dt)
{
	if(!m_IsActivate)
		return 1.0f;

	if(m_IsGoingDown)
	{
		m_CurrentTickScale -= dt;
		if(m_CurrentTickScale <= 0.35f)
		{
			m_CurrentTickScale = 0.35f;
			m_IsGoingDown = false;
		}
		return m_CurrentTickScale;
	}
	
	if(m_Counter > 0)
	{
		m_Counter -= dt;
	}	
	else if(m_CurrentTickScale <= 1.0f)
	{
		m_CurrentTickScale += dt;
		if(m_CurrentTickScale >= 1.0f)
		{
			m_CurrentTickScale = 1.0f;
			m_IsActivate = false;
		}
	}

	return m_CurrentTickScale;

	

	
	
}


